#include <Mesh.h>

	/********************************/
	/*			Members				*/
	/********************************/

		/********************************/
		/*			Construcors			*/
		/********************************/
			
            Mesh::Mesh(){
                m_VertexTemplate = new VertexTemplate();
                Meshes.push_back(this);
                offset=TotalAttributes;
			}
			
		/********************************/
		/*			Methods				*/
		/********************************/

            void Mesh::Display(){

                m_Material->program->Use();
                BindAttribute();
                m_Material->SendSharedUniforms();

                for(int i=0; i< m_VertexTemplate->attributes.size();i++){
                    glVertexAttribPointer(m_VertexTemplate->attributes[i]->id,4,GL_FLOAT, GL_FALSE,
                                          ((m_VertexTemplate->attributes[i]->size*4))*sizeof(float),
                                          (void*)+m_VertexTemplate->attributes[i]->offset);
                }

                glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)+0);
            }

            void Mesh::NewTriangle(Vertex *v1, Vertex *v2, Vertex *v3){
                Triangle * triangle = new Triangle(m_Triangles.size()*3);
                triangle->SetVertices(v1,v2,v3);
                m_Triangles.push_back(triangle);
            }

            void Mesh::RemoveTriangle(int pos){
                Triangle * triangle = m_Triangles.at(pos);
                triangle->DeleteTriangle();
                m_Triangles.erase(m_Triangles.begin()+ pos);
                UpdateMeshes();
            }

            Vertex &Mesh::NewVertex(){
                Vertex * vertex = new Vertex();
                vertex->SetTemplate(m_VertexTemplate);
                vertex->offset= m_Vertices.size()*m_VertexTemplate->totalSize;
                vertex->vertexId= m_Vertices.size();
                m_Vertices.push_back(vertex);
                vertex->InsertVertexBuffer();
                return *vertex;
            }

            void Mesh::RemoveVertex(int pos){
                Vertex * vertex = m_Vertices.at(pos);
                int triangleCount =vertex->m_Triangles.size();
                for(int i=triangleCount-1; i>= 0; i--){
                    RemoveTriangle(i);
                }
                Vertex::s_Vertices.erase(Vertex::s_Vertices.begin()+ vertex->offset,
                                         Vertex::s_Vertices.begin()+ vertex->offset+vertex->size);
                m_Vertices.erase(m_Vertices.begin()+pos);
                UpdateMeshes();

            }

             VertexTemplate &    Mesh::GetVertexTemplate(){
                return *m_VertexTemplate;
             }

            VertexTemplate *Mesh::SetVertexTemplate(){
                m_VertexTemplate    =   new VertexTemplate();
                return m_VertexTemplate;
            }

            void Mesh::SetVertexTemplate(VertexTemplate & t){
                m_VertexTemplate=&t;
            }

            void Mesh::SetVertexTemplate(VertexTemplate * t){
                m_VertexTemplate=t;
            }

            void Mesh::UpdateVertices(){
                for(int i=0; i< m_Vertices.size();i++){
                //    m_Vertices.at(i).offset =offset+   m_VertexTemplate->totalSize*i;
                }
            }

            void Mesh::BindAttribute(){
                for(int i=0; i< m_VertexTemplate->attributes.size();i++){
                    glEnableVertexAttribArray(m_VertexTemplate->attributes[i]->id);
                }
            }



            void Mesh::PrintVertices(){
                for(int i=0; i<12;i++){

                //    qDebug()<< datas[(i*4)] <<","<< datas[(i*4)+1]<<","<<datas[(i*4)+2]<<","<<datas[(i*4)+3];

                }

            }



    /********************************
    /*			Static
	/********************************/

        /********************************
        /*			Properties
		/********************************/

             vector<Vertex*>  Mesh::s_Vertices;
             vector<GLuint>   Mesh::s_Indices;

             vector<Mesh*>    Mesh::Meshes;
             int              Mesh::TotalAttributes;



		
        /********************************
        /*			Methods
		/********************************/
			

            Mesh * Mesh::NewRect(float width, float height)
            {
                Mesh * mesh = new Mesh;

                float width_2   =   width/2.0f;
                float height_2  =   height/2.0f;

                printf("Width : %f \n", width_2);
                printf("Height %f \n", height_2);

                /*mesh->
                 *(  Vertex::New(

                                                new vec4( -width_2, height_2, -2.0,1.0),
                                                new vec4( 1.0, 0.0, 0.0,1.0),
                                                new vec4( 1.0, 0.0, 0.0,1.0),
                                                new vec4( 0.0, 0.0, 0.0,0.0)

                                            )
                                 );

                mesh->AddVertex(Vertex::New
                                            (
                                                new vec4( width_2, height_2, -2.0,1.0),
                                                new vec4( 1.0, 0.0, 0.0,1.0),
                                                new vec4( 1.0, 0.0, 0.0,1.0),
                                                new vec4( 1.0, 0.0, 0.0,0.0)
                                            )
                                );

                mesh->AddVertex(Vertex::New
                                (
                                    new vec4( width_2, -height_2, -2.0,1.0),
                                    new vec4( 1.0, 0.0, 0.0,1.0),
                                    new vec4( 1.0, 0.0, 0.0,1.0),
                                    new vec4( 1.0, 1.0, 0.0,0.0)
                                ));

                mesh->AddVertex(Vertex::New
                                (
                                    new vec4( -width_2, -height_2, -2.0,1.0),
                                    new vec4( 1.0, 0.0, 0.0,1.0),
                                    new vec4( 1.0, 0.0, 0.0,1.0),
                                    new vec4( 0.0, 1.0, 0.0,0.0)
                                ));

                mesh->AddFace(0,1,2);
                mesh->AddFace(2,0,3);

                BufferObject::FeedBuffers();*/

                return mesh;
            }




            GLuint * Mesh::ReturnIndices(){
               return &s_Indices[0];
            }

            float * Mesh::ReturnVertices(){

                float * tab = new float[TotalAttributes];

                int index=0;

                for(int i=0; i< Meshes.size(); i++){
                    for(int j=0; j<Meshes.at(i)->m_Vertices.size();j++)
                    {
                        for(int k=0; k< Meshes.at(i)->GetVertexTemplate().totalSize; k++){
                  //          tab[index]=Meshes.at(i)->m_Vertices.at(j)->datas[k];
                            index++;
                        }
                    }
                }
                return tab;
            }


            void Mesh::UpdateMeshes(){
             //   if(Meshes.size()>0){
            //        Meshes.at(0).offset=0;
            //        for(int i=1; i< Meshes.size();i++){
            //            Meshes.at(i).offset =
          //                                      Meshes.at(i-1).offset+
           //                                     (
      //                                              Meshes.at(i-1).m_VertexTemplate.totalSize *
      //                                              Meshes.at(i-1).m_Vertices.size()
       //                                         );
      //                  Meshes.at(i).UpdateVertices();
      //                  Meshes.at(i).UpdateTriangles();
         //           }
            //    }

            }
		




